/**
 * Date Created: Apr 15, 2009
 */

package forteresce.portprofile.gui.panels;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;

import org.apache.log4j.Logger;

import forteresce.portprofile.config.constants.ProfileConstants;
import forteresce.portprofile.config.enums.SystemPropertiesEnum;
import forteresce.portprofile.gui.PortProfileFrame;
import forteresce.portprofile.gui.dialogs.PortProfileDialogs;
import forteresce.portprofile.gui.events.ShowProfilesEvent;
import forteresce.portprofile.gui.events.ShowWaitEvent;
import forteresce.portprofile.profiles.bean.ProfileBean;
import forteresce.portprofile.profiles.data.ProfileIniData;
import forteresce.portprofile.profiles.util.ProfileUtil;
import forteresce.portprofile.profiles.util.SystemUtil;
import forteresce.portprofile.profiles.util.ZipUtil;

/**
 * A simple panel to be used as a place holder for the profile selection 
 * @author forteresce
 */
public class ProfilesExportPanel extends JPanel implements ActionListener {
	private static Logger log = Logger.getLogger(ProfilesExportPanel.class);
	
	private JComboBox profilesCombo;
	private JTextField exportFileName;

	private JFrame parentFrame;
	
	private static final long serialVersionUID = -3439515683762406325L;

	public ProfilesExportPanel(JFrame parentFrame) {
		super();

		//store the reference to parent frame
		this.parentFrame = parentFrame;
		
		//the regular ones
		setMinimumSize(ProfileConstants.MAIN_PANEL_DIM);
		setLayout(new GridBagLayout());
		
		//add the components
		addComponents();
	}
	
	private void addComponents() {
		Dimension labelDimension = new Dimension(125, 25);
		Dimension fieldDimension = new Dimension(160, 25);

		JLabel selectLabel = new JLabel("Select a profile:");
		selectLabel.setHorizontalAlignment(SwingConstants.RIGHT);
		selectLabel.setPreferredSize(labelDimension);

		profilesCombo = new JComboBox();
		profilesCombo.setPreferredSize(fieldDimension);
		profilesCombo.setBorder(BorderFactory.createEtchedBorder());
		profilesCombo.setRenderer(new ProfileComboRenderer());
		
		JLabel exportAsLabel = new JLabel("Export As:");
		exportAsLabel.setHorizontalAlignment(SwingConstants.RIGHT);
		exportAsLabel.setPreferredSize(labelDimension);
		
		exportFileName = new JTextField();
		exportFileName.setPreferredSize(fieldDimension);
		exportFileName.setText("ff_ppz_" + System.currentTimeMillis());
		
		
		JButton exportButton = new JButton("Export");
		exportButton.addActionListener(this);
		
		//add the components to the pane
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = new Insets(5, 10, 5, 10);
		
		constraints.gridx = 0;
		constraints.gridy = 0;
		add(selectLabel, constraints);

		constraints.gridx = 1;
		constraints.gridy = 0;
		add(profilesCombo, constraints);

		constraints.gridx = 0;
		constraints.gridy = 1;
		add(exportAsLabel, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 1;
		add(exportFileName, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 2;
		constraints.gridwidth = 2;
		add(exportButton, constraints);
	}
	
	/**
	 * loads the profile values by using the util and fills the combo with them 
	 */
	public void loadProfileValues() throws Exception {
		ProfileIniData profileIniData = ProfileUtil.load();
		
		List<ProfileBean> profiles = profileIniData.getProfileBeanList();
		for(ProfileBean profile : profiles) {
			profilesCombo.addItem(profile);
		}
		
		log.debug("Loaded " + profileIniData.getProfileBeanList().size() + " profile(s)!!");
	}
	
	/**
	 * All of the main logic is performed on the user action
	 */
	public void actionPerformed(ActionEvent event) {
		
		if (!exportFileName.getText().matches("\\w+")) {
			PortProfileDialogs.showError(parentFrame, "Please enter a valid export as file name.");
			return;
		}
			
		
		if (parentFrame instanceof PortProfileFrame) {
			((PortProfileFrame) parentFrame).dispatchEvent(new ShowWaitEvent(
					parentFrame, "Please wait while profile is compressed."));
		}
		
		ProfileExporter exporter = new ProfileExporter();
		exporter.execute();
	}
	
	/**
	 * List renderer for the profile combo so that we can directly add profiles to it and use them later 
	 * @author forteresce
	 */
	private class ProfileComboRenderer extends JLabel implements ListCellRenderer {

		private static final long serialVersionUID = 2938118196975152553L;
		
		public ProfileComboRenderer() {
			setOpaque(true);
            setHorizontalAlignment(CENTER);
            setVerticalAlignment(CENTER);
		}
		
		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {

            if (isSelected) {
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }

            //Set the text
            ProfileBean profile = (ProfileBean) value;
            setText(profile.getName());
            
            if(null != profile.getDefault() && "1".equals(profile.getDefault())) {
            	setFont(getFont().deriveFont(Font.BOLD));
            } else {
            	setFont(getFont().deriveFont(Font.PLAIN));
            }

            return this;
		}
	}
	
	/**
	 * An inner swing worker class to do the profile export 
	 * @author forteresce
	 */
	class ProfileExporter extends SwingWorker<Boolean, Void> {
		private String destZip;
		private boolean profileInUse;

		@Override
		protected Boolean doInBackground() throws Exception {
			ProfileBean profile = (ProfileBean) profilesCombo.getSelectedItem();
			String profilePath = "1".equals(profile.getIsRelative()) ? SystemUtil.getProfilePath() + profile.getPath() : profile.getPath();
			
			//check if profile is in use
			profileInUse = SystemUtil.isProfileInUse(profilePath);
			if (profileInUse) {
				return false;
			}
			
			destZip = SystemPropertiesEnum.USER_HOME.get() + SystemPropertiesEnum.FILE_SEPARATOR.get() + exportFileName.getText() + ProfileConstants.PROFILE_FILE_EXTN;
			boolean result = ZipUtil.zip(profilePath, destZip);
			
			return Boolean.valueOf(result);
		}
		
		@Override
		protected void done() {
			super.done();
			try {
				if (parentFrame instanceof PortProfileFrame) {
					((PortProfileFrame) parentFrame) .dispatchEvent(new ShowProfilesEvent(parentFrame));
				}
				
				if (profileInUse) {
					PortProfileDialogs.showError(parentFrame, "The selected profile is currently in use.\nPlease close firefox or choose another profile.");
				} else if (!get().booleanValue()) {
					PortProfileDialogs.showError(parentFrame, "Error while exporting profile.");
				} else {
					PortProfileDialogs.showInfo(parentFrame, "Profile successfully exported as:\n" + destZip);
				}
			} catch (InterruptedException e) {
				log.error(e);
			} catch (ExecutionException e) {
				log.error(e);
			}
		}
	}
}
